package solver.moves;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import model.MachineSelector;
import model.Solution;
import model.SolverEnvironment;

public class ProcessMoveEliminator extends AbstractComplexMove{

	ArrayList<Integer> p_id;
	static int COUNT_UPDATE=20;
	int count=0;
	
	public ProcessMoveEliminator(SolverEnvironment env) {
		super(env);
		p_id = new ArrayList<Integer>();
	}

	@Override
	public boolean performMove() {
		boolean success = false;
//		if(count--<=0 || p_id.size()==0)
			updateP_id();
		long init_cost=getCc().getNewSolutionCost();
		Solution pot_sol = env.getPotentialSolution();
		
		Collections.shuffle(p_id,getRandom());
		for (Integer p: p_id){
		
//		int start = getRandom().nextInt(getProblem().P);
//		for(int _p=start;_p<start+getProblem().P;_p++){
//			int p = _p%getProblem().P;
//			long local_cost=getCc().getNewSolutionCost();
			int orig_m1_index = getInitial_solution().getMachineIdForProcessId(p);
			int curr_m1_index = pot_sol.getMachineIdForProcessId(p);
			if(orig_m1_index==curr_m1_index)
				continue;
			//We are at different machines

			//Lets just try to move it back
			if(testWithoutMove(p, curr_m1_index, orig_m1_index)){				
//				long new_cost=env.getCostCalculator().getNewSolutionCost()+
				long delta = 
						env.getCostCalculator().getProcessMoveToMachineCost(pot_sol, p, curr_m1_index, orig_m1_index);
//				if(new_cost<=init_cost){
				if(delta<=0){
					makeMove(p, curr_m1_index, orig_m1_index);
					getCc().updateNewSolutionCost();
					success=true;
					continue;
//					return true;
				}
			}
			
			
			List<Integer> l1 = pot_sol.getProcessesForMachine(orig_m1_index);
			if (l1.size()==0)
				continue;
			Collections.shuffle(l1,getRandom());
			for(Integer p2:l1){
//				if(getInitial_solution().getMachineIdForProcessId(p2)==orig_m1_index)
//					continue;
				if (getIv().isProcessExchangeFeasibleNoSchedule(p, curr_m1_index, p2, orig_m1_index)){
					long new_cost=env.getCostCalculator().getNewSolutionCost()+
							env.getCostCalculator().getProcessExcahngeProfit(pot_sol, p, p2,curr_m1_index,orig_m1_index);
					if(new_cost<=init_cost 
//							|| getInitial_solution().getMachineIdForProcessId(p2)==curr_m1_index
					)
					{
						makeExchange(p,curr_m1_index, p2, orig_m1_index);
						getCc().updateNewSolutionCost();
						success=true;
						break;
					}
				}
			}
		}
		getCc().clearDelta();

		return success;
	}
	
	private void updateP_id(){
		p_id.clear();
		for(int _p=0;_p<getProblem().P;_p++){
			int orig_m1_index = getInitial_solution().getMachineIdForProcessId(_p);
			int curr_m1_index = getCurrent_solution().getMachineIdForProcessId(_p);
			if(orig_m1_index!=curr_m1_index)
				p_id.add(_p);
		}
		count = COUNT_UPDATE;
	}
	
	
}
